/*
 * Copyright 2012 Zach Whaley
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package me.zachwhaley.android;

import me.zachwhaley.android.utils.ActionBarHelper;
import me.zachwhaley.android.utils.ActivityHelper;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;

/**
 * Abstract base activity that models common functionality for all activities
 * 
 * @author Zach Whaley
 */
public abstract class BaseActivity extends FragmentActivity
{
	/** {@link ActivityHelper} */
	ActivityHelper activityHelper = ActivityHelper.createInstance(this);
	/** {@link ActionBarHelper} */
	ActionBarHelper actionBarHelper = ActionBarHelper.createInstance(this);

	/**
	 * Opens a new activiy or fragment with the input intent
	 * 
	 * @param intent
	 */
	public void openActivityOrFragment(Intent intent)
	{
		// If the app is running on a tablet
		// show a detail fragment within the current activity
		if (activityHelper.isTablet())
		{
			try
			{
				// Get the fragment information
				FragmentInfo fragInfo = onShowDetailFragment();
				// Create the new Fragment from the fragment info
				Fragment details = (Fragment) fragInfo.getFragmentClass()
						.newInstance();

				// Transition and show the new fragment
				final FragmentTransaction ft = getSupportFragmentManager()
						.beginTransaction();
				ft.replace(fragInfo.getContainerID(), details);
				ft.commit();
			}
			catch (InstantiationException e)
			{
				throw new IllegalStateException("Error creating new fragment.",
						e);
			}
			catch (IllegalAccessException e)
			{
				throw new IllegalStateException("Error creating new fragment.",
						e);
			}
		}
		// Otherwise open a new Activity
		else
			startActivity(intent);
	}

	/**
	 * Returns the {@link ActionBarHelper} for this activity.
	 * 
	 * @return {@link ActionBarHelper}
	 */
	protected ActionBarHelper getActionbarHelper()
	{
		return actionBarHelper;
	}

	/**
	 * Returns the {@link ActivityHelper} for this activity
	 * 
	 * @return {@link ActivityHelper}
	 */
	protected ActivityHelper getActivityHelper()
	{
		return activityHelper;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public MenuInflater getMenuInflater()
	{
		return actionBarHelper.getMenuInflater(super.getMenuInflater());
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		actionBarHelper.onCreate(savedInstanceState);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected void onPostCreate(Bundle savedInstanceState)
	{
		super.onPostCreate(savedInstanceState);
		actionBarHelper.onPostCreate(savedInstanceState);
	}

	/**
	 * Base action bar-aware implementation for
	 * {@link Activity#onCreateOptionsMenu(android.view.Menu)}.
	 * 
	 * Note: marking menu items as invisible/visible is not currently supported.
	 */
	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.feedback_menu, menu);

		return super.onCreateOptionsMenu(menu);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		if (item.getItemId() == R.id.feedback)
		{
			Toast.makeText(this, "Send Feedback", Toast.LENGTH_SHORT).show();
			return true;
		}
		else
			return super.onOptionsItemSelected(item);
	}

	/**
	 * Abstract method called when a detail fragment is being shown
	 * 
	 * @return Additional information on the fragment
	 */
	protected abstract FragmentInfo onShowDetailFragment();

	/**
	 * Fragment Information Class carries additional information on a fragment.
	 * 
	 * @author Zach Whaley
	 */
	protected class FragmentInfo
	{
		private int containerID;
		@SuppressWarnings("rawtypes")
		private Class fragmentClass;
		private String tag;

		/**
		 * FragmentInfo Constructor
		 * 
		 * @param fragmentClass
		 * @param containerID
		 * @param tag
		 */
		@SuppressWarnings("rawtypes")
		public FragmentInfo(Class fragmentClass, int containerID, String tag)
		{
			this.fragmentClass = fragmentClass;
			this.containerID = containerID;
			this.tag = tag;
		}

		/**
		 * FragmentInfo Constructor
		 * 
		 * @param fragmentClass
		 * @param containerID
		 */
		@SuppressWarnings("rawtypes")
		public FragmentInfo(Class fragmentClass, int containerID)
		{
			this.fragmentClass = fragmentClass;
			this.containerID = containerID;
			this.tag = "";
		}

		/**
		 * Returns the Fragment class type
		 * 
		 * @return Fragment class type
		 */
		@SuppressWarnings("rawtypes")
		public Class getFragmentClass()
		{
			return fragmentClass;
		}

		/**
		 * Returns the container ID
		 * 
		 * @return container ID
		 */
		public int getContainerID()
		{
			return containerID;
		}

		/**
		 * Returns the tag
		 * 
		 * @return tag
		 */
		public String getTag()
		{
			return tag;
		}
	}
}
